/*
 *
 * Copyright (c) 2020 The Raptor Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef RAPTOR_LITE_SRC_WINDOWS_TCP_LISTENER_H_
#define RAPTOR_LITE_SRC_WINDOWS_TCP_LISTENER_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "raptor-lite/utils/list_entry.h"
#include "raptor-lite/utils/mpscq.h"
#include "raptor-lite/utils/sync.h"
#include "raptor-lite/utils/thread.h"

#include "src/common/resolve_address.h"
#include "src/common/sockaddr.h"
#include "src/common/common.h"

namespace raptor {

class AcceptorHandler;
class Property;
class PollingThread;

struct TcpListenObject;

class TcpListener final : public internal::EventReceivingService {
public:
    explicit TcpListener(AcceptorHandler *service);
    ~TcpListener();

    raptor_error Init(PollingThread *poll_thread);

    raptor_error AddListeningPort(const raptor_resolved_address *addr);
    raptor_error Start();
    void Shutdown();

private:
    void OnEventProcess(EventDetail *detail) override;
    void OnEventProcessImpl(EventDetail *detail);

    raptor_error StartAcceptEx(SOCKET listen_fd, raptor_resolved_address *addr,
                               struct TcpListenObject *sp);
    void ParsingNewConnectionAddress(const TcpListenObject *sp, raptor_resolved_address *server,
                                     raptor_resolved_address *client);

    raptor_error GetExtensionFunction(SOCKET fd);
    void ProcessProperty(SOCKET fd, const Property &p);

    void WorkThread(void *);

    AcceptorHandler *service_;
    bool shutdown_;

    LPFN_ACCEPTEX AcceptEx_;
    LPFN_GETACCEPTEXSOCKADDRS GetAcceptExSockAddrs_;
    PollingThread *poll_thread_;

    ListEntry list_head_;

    Thread thd_;

    Mutex mtx_;

    std::vector<SOCKET> listen_fds_;

    AtomicInt64 count_;
    Mutex cmtx_;
    ConditionVariable cv_;
    MultiProducerSingleConsumerQueue mpscq_;
};

} // namespace raptor

#endif // RAPTOR_LITE_SRC_WINDOWS_TCP_LISTENER_H_
